﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using MyFloridaHouse.libSvBingMapsMultiShape;
using MyFloridaHouse.libSvCommonUtilities;
using MyFloridaHouse.libSvOpenDistricts.Census;
using MyFloridaHouse.libSvOpenDistricts.Districts;
using MyFloridaHouse.libSvOpenDistricts.enumerations;
using MyFloridaHouse.libSvOpenDistricts.MapShapes;
using MyFloridaHouse.libSvOpenDistricts.MapTools;
using MyFloridaHouse.ServiceConn.DistrBldrSvcRef;
using MyFloridaHouse.libSvUtilities;

namespace MyFloridaHouse.libSvOpenDistricts.ViewModel
{
    public partial class ViewModelBase
    {
        private DistrictPlan _districtPlan;
        public DistrictPlan districtPlan
        {
            get { return _districtPlan; }
            set
            {
                if (_districtPlan != value)
                {
                    _districtPlan = value;

                    NotifyPropertyChanged("districtPlan");
                }
            }
        }

        private MapShapeLayer _districtMapLayer;
        public MapShapeLayer districtMapLayer
        {
            get { return _districtMapLayer; }
            set { if (_districtMapLayer != value) { _districtMapLayer = value; } }
        }
        #region command methods



        #endregion

        #region methods

        public enumLassoMode getLassoMode()
        {
            if (mapMode == enumMapMode.Click)
                return enumLassoMode.Click;
            else if (mapMode == enumMapMode.Lasso)
                return enumLassoMode.Lasso;
            else
                return enumLassoMode.Off;
        }




        //private void OnDistrictPlanFileLoaded(object sender, DistrictPlanFileLoadedEventArgs args)
        //{
        //    if (args.loadType == enumDistrictPlanLoadType.LoadedShapeUogIDs)
        //    {
        //        BuildDistrictShapesAll();
        //    }
        //    else if (args.loadType == enumDistrictPlanLoadType.LoadedShapeWKT)
        //    {
        //        BuildDistrictShapesAllWKT(districtPlan.districtWKT, districtPlan.censusGeometry.ToCondensedList(districtPlan.districtCount));
        //    }

        //}

        private void OnDistrictShapesChanged(object sender, EventArgs args)
        {
            BuildChangedShapes();
        }


        public void LassoCompleted()
        {
            GetShapeUogIDs();

        }


        private void InitializeDistrictShapes()
        {
            ObservableCollection<RegionDTO> regionList = new ObservableCollection<RegionDTO>();
            List<RegionDetails> regionDetailList = new List<RegionDetails>();

            // create the number of district shapes requested
            for (int districtID = 0; districtID <= districtPlan.districtCount; districtID++)
            {
                InitializeDistrictShape(regionList, regionDetailList, districtID);
            }

            // add the new district shapes to the map
            districtMapLayer.LoadRegions(districtMapLayer.layerID, regionList, regionDetailList);


        }

        private static void InitializeDistrictShape(ObservableCollection<RegionDTO> regionList, List<RegionDetails> regionDetailList, int districtID)
        {
            // REGION MAP INFO
            // create a map region for this new district
            RegionDTO rgn = new RegionDTO();
            rgn.regionID = districtID;
            rgn.mapObject = Constants.WKT_EMPTY_SHAPE;
            rgn.boundingBox = new BoundingBoxDTO();
            // Not clear why BoundingBoxDTO constructor doesn't initialize northwest and southeast, so have to do it here
            rgn.boundingBox.northWest = new PointDTO();
            rgn.boundingBox.southEast = new PointDTO();

            rgn.boundingBox.northWest.latitude = Constants.WKT_EMPTY_SHAPE_LATITUDE;
            rgn.boundingBox.northWest.longitude = Constants.WKT_EMPTY_SHAPE_LONGITUDE;
            rgn.boundingBox.southEast.latitude = Constants.WKT_EMPTY_SHAPE_LATITUDE;
            rgn.boundingBox.southEast.longitude = Constants.WKT_EMPTY_SHAPE_LONGITUDE;
            regionList.Add(rgn);


            // REGION DETAILS INFO
            // create a region detail for this new district
            RegionDetails rgnDetails = new RegionDetails();

            // Need to override the district region with the colors for the district
            rgnDetails.unselected.stroke = new SolidColorBrush(Colors.Blue);
            rgnDetails.unselected.strokeThickness = 1;

            rgnDetails.selected.stroke = new SolidColorBrush(Colors.Blue);
            rgnDetails.selected.strokeThickness = 1;

            regionDetailList.Add(rgnDetails);
        }

        private void createDistrictMapLayer()
        {
            // need to simulate a response from the service with information from the AppLayers table
            LayerDTO districtLayer = new LayerDTO();
            districtLayer.layerid = -1;
            districtLayer.layername = "District";
            districtLayer.defaultstrokecolor = "BLUE";
            districtLayer.defaultfillcolor = "ORANGE";
            districtLayer.zoommin = 1;
            districtLayer.zoommax = 21;

            //TODO: Delete these when removed from appLayer
            districtLayer.isStoreInMemory = false;
            districtLayer.isGraphLayer = false;
            districtLayer.isFindLayer = false;

            // create a new layer and add it to the map
            districtMapLayer = new MapShapeLayer(serviceDAL, myXamlMainMap, districtLayer, MapShapeLayer.enuMLayerAddLocation.bottom);
            districtMapLayer.isFillByRegionIndexType = true;
            districtMapLayer.predefinedRegions = false;
            districtMapLayer.showLayer = true;
        }

        public void DistrictBuildWithShaded(int buildDistrictID)
        {
            List<UOG> uogIDList = new List<UOG>();
            foreach (var rgn in buildLayerList[buildLayerListSelectedIndex].layerRegionList)
            {
                //NOTE: looking for any region on the build layer that has fill turned on
                if (!((SolidColorBrush)rgn.regionShape.Fill).Color.Equals(Colors.Transparent))
                {
                    uogIDList.Add(new UOG(rgn.regionID));
                }
            }
            districtPlan.MoveShapesToNewDistrict(buildDistrictID, uogIDList);
        }

        
//  TODO: Remove with WKT drop
        //private MapMultiShapeBase ConvertWKTtoMultiMapShape(byte[] WKT)
        //{
        //    MapMultiShapeBase mapShape = null;
        //    if (WKT.Length != 0)
        //    {
        //        string wkt = CompressionManager.Decompress(WKT);
        //        if (wkt.Trim().Length <= 0)
        //        {
        //            wkt = Constants.WKT_EMPTY_SHAPE;
        //        }

        //        mapShape = MapShapeTools.BuildShape(wkt);
        //    }
        //    return mapShape;

        //}

        private void BuildChangedShapes()
        {
            // now all shapes have been reassigned, so redisplay every changed district
            List<string> condensedDistrictList = districtPlan.ToCondensedList(districtPlan.districtCount);
            foreach (var districtID in districtPlan.changedDistrictsList)
            {
                // display each district using the shapes left in them after reassignment
                //todo: check this for out of range index
                GetDistrictShape(districtID, condensedDistrictList[districtID]);
                GetDistrictDataSummary(districtID, condensedDistrictList[districtID]);
            }
        }

        //  TODO: Remove with WKT drop
        //public void BuildDistrictShapesAllWKT(List<byte[]> iDistrictWKT, List<string> condensedDistrictList)
        //{
           
        //    districtPlan.districtWKT = iDistrictWKT;
            
        //    for (int districtID = 1; districtID < districtPlan.districtWKT.Count; districtID++)
        //    {
        //        // no point in building the shapes if there isn't anything in it
        //        if (districtPlan.districtWKT[districtID].Length > 0)
        //        {
        //            // don't need to ask the web service for the shape since we already have the WKT
        //            // so cal replaceDistrictShape instead of BuildDistrictShape
        //            ReplaceDistrictShape(districtID, districtPlan.districtWKT[districtID]);
        //            GetDistrictDataSummary(districtID, condensedDistrictList[districtID]);
        //        }
        //    }
        //}

        public void BuildDistrictShapesAll()
        {
            // for each known district,  ignore zero(unassinged) 
            // look in censusGeometry for it's condensed version
            // send the condensed version to the database

            List<string> condensedDistrictList = districtPlan.ToCondensedList(districtPlan.districtCount);
            for (int districtID = 1; districtID < condensedDistrictList.Count; districtID++)
            //    for (int districtID = 1; districtID < condensedDistrictList.Count; districtID++)
            {
                // no point in building the shapes if there isn't anything in it
                if (condensedDistrictList[districtID].Length > 0)
                {
                    GetDistrictShape(districtID, condensedDistrictList[districtID]);
                    GetDistrictDataSummary(districtID, condensedDistrictList[districtID]);
                }
            }

        }

        public void ReloadDistrictShapesAll()
        {
            List<string> condensedDistrictList = districtPlan.ToCondensedList(districtPlan.districtCount);
            foreach (var dist in districtPlan.districtList)
            {
                districtMapLayer.ReplaceRegionShape(dist.districtID, dist.districtMultiMapShape, dist.boundingBox);
                if (condensedDistrictList[dist.districtID].Length > 0)
                {
                    GetDistrictDataSummary(dist.districtID, condensedDistrictList[dist.districtID]);
                }
            }
        }

        public void BuildDistrictSummaryAll()
        {
            List<string> condensedDistrictList = districtPlan.ToCondensedList(districtPlan.districtCount);
            for (int districtID = 1; districtID < districtPlan.districtCount; districtID++)
            {
                // no point in building the shapes if there isn't anything in it
                if (condensedDistrictList[districtID].Length > 0)
                {
                    GetDistrictDataSummary(districtID, condensedDistrictList[districtID]);
                }
            }
        }


        public void ReplaceDistrict(DistrictShapeSTO result)
        {
            // don't display the shape for the default (unassigned) district (district 0)
            if (result.districtID != 0)
            {
                districtPlan.UpdateDistrictMetaData(result);
                districtPlan.districtList[result.districtID].districtMultiMapShape = MapShapeTools.BuildShape(result.mapMultiShapeDTO);
                districtMapLayer.ReplaceRegionShape(result.districtID, districtPlan.districtList[result.districtID].districtMultiMapShape, result.districtShapeBoundingBox);

            }

        }

        public void ReplaceDistrictDataSummary(DistrictDataSummarySTO result)
        {
            if (result.districtDataSummaryList == null)
            {
                // todo: log this error, should never happen
                MessageBox.Show("Database returned a null districtDataSummaryList for District ID " + result.districtID.ToString());
            }
            else
            {

                // don't display the shape for the default (unassigned) district (district 0)
                dataGridManager.ReplaceSummaryDataGridDataRow(result.districtID
                                            , districtPlan.districtList[result.districtID].targetPopulation
                                            , result.districtDataSummaryList);
            }
        }

        #endregion

    }
}
